package com.esunrising.esungsc.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.esunrising.esungsc.common.utils.ESUNGSCUtil;
import com.esunrising.esungsc.common.utils.HttpUtil;
import com.esunrising.esungsc.config.GSCAPIConfig;
import com.esunrising.esungsc.dto.FIGLZWPZ;
import com.esunrising.esungsc.entity.BFCustomItem;
import com.esunrising.esungsc.entity.FIGLAccDocAssistance;
import com.esunrising.esungsc.entity.FIGLAccDocEntry;
import com.esunrising.esungsc.entity.FIGLAccountingDocument;
import com.esunrising.esungsc.exception.ESUNException;
import com.esunrising.esungsc.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class GSCServiceImpl implements GSCService {


    @Resource
    private RestTemplate restTemplate;

    @Resource
    private GSCAPIConfig gscapiConfig;


    @Resource
    private BFCustomeItemService bfCustomeItemService;

    @Resource
    private SysConfigService sysConfigService;


    @Override
    public String getHttpBaseUrl(){
        return sysConfigService.findConfigValueByConfigKey("basePath-test");
    }
    @Override
    public HttpHeaders getHttpHeaders(){
        Map<String, List<String>> requestHeaders = new HashMap<>();
        requestHeaders.put("Content-Type", List.of(sysConfigService.findConfigValueByConfigKey("Content-Type")));
        requestHeaders.put("Accept-Language", List.of(sysConfigService.findConfigValueByConfigKey("Accept-Language")));
        requestHeaders.put("X-ECC-Current-Tenant", List.of(sysConfigService.findConfigValueByConfigKey("X-ECC-Current-Tenant")));
        requestHeaders.put("Authorization", List.of(sysConfigService.findConfigValueByConfigKey("Authorization")));

        HttpHeaders headers = new HttpHeaders();
        headers.addAll(new LinkedMultiValueMap<>(requestHeaders));

        return headers;
    }

    @Override
    public String callGCApi(String uri, HttpHeaders headers, Map<String, Object> bodyParam){

        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(bodyParam, headers);
        // 发送请求
        try {
            ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);
            if(response.getStatusCodeValue() == 200){
                // 返回结果数据 JSON字符串
                return response.getBody();

            }else{
//            System.out.println(response.getStatusCode());
//            System.out.println(response.getStatusCodeValue());
//            System.out.println(response.getHeaders());
//            System.out.println(response.getBody());
                return null;
            }
        } catch (HttpClientErrorException e){
            // TODO:考虑根据错误码进行判断后写入日志
//            if(HttpStatus.NOT_FOUND.equals(e.getStatusCode())){
//                throw new ESUNException("请求失败, 参考错误："+e.getMessage());
//            }
            throw new ESUNException("请求失败, 参考错误："+e.getMessage());
        } catch (RestClientException e) {
            throw new ESUNException("请求失败");
        }
    }

    @Override
    public String callGCApi(String uri, Map<String, Object> bodyParam) {
        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(bodyParam, getHttpHeaders());
        // 发送请求
        try {
            ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);
            if(response.getStatusCodeValue() == 200){
                // 返回结果数据 JSON字符串
                return response.getBody();

            }else{
                return null;
            }
        } catch (HttpClientErrorException e){
            // TODO:考虑根据错误码进行判断后写入日志
//            if(HttpStatus.NOT_FOUND.equals(e.getStatusCode())){
//                throw new ESUNException("请求失败, 参考错误："+e.getMessage());
//            }
            throw new ESUNException("请求失败, 参考错误："+e.getMessage());
        } catch (RestClientException e) {
            throw new ESUNException("请求失败");
        }
    }

    /**
     * 保存接口调用记录
     * @param dwbh 单位编号
     * @param orgId 账务核算组织ID
     * @param orgCode 财务核算组织编号
     * @param ledger 账务核算账簿
     * @param type 接口类型
     * @param res 接口调用结果说明，正常为“获取成功”，异常为错误信息
     */
    @Override
    public void saveLog(String dwbh, String orgId, String orgCode, String ledger, String type, String res) {
        // TODO 接口调用记录保存到数据库表中
    }

    /**
     * 保存接口调用记录
     *
     * @param dwbh     单位编号
     * @param orgId    账务核算组织ID
     * @param orgCode  财务核算组织编号
     * @param ledger   账务核算账簿
     * @param type     接口类型
     * @param dateTime 接口调用时间
     */
    @Override
    public void updateSyncTime(String dwbh, String orgId, String orgCode, String ledger, String type, LocalDateTime dateTime) {
        // TODO 接口调用时间保存/更新到数据库表中

    }

    /**
     * 更新接口全局调用时间
     *
     * @param type 接口类型
     */
    @Override
    public void updateApiTime(String type) {
        // TODO 接口全局调用时间保存/更新到数据库表中
    }

    /**
     * 调用API接口获取GSC账务核算项目字典数据
     *
     * @param year 会计年度
     * @param hszzid 核算组织ID
     * @param lastChangedOn 获取同步日期；调用方记录获取日期，下次调用传输上次获取日期,获取此日期后的增量数据,格式: yyyy-MM-dd HH:mi:ss
     * @param endDate 获取结束日期
     * @return GSC账务核算项目字典数据
     */
    @Override
    public List<BFCustomItem> getApiCustomItem(String year, String hszzid, String lastChangedOn, String endDate) {
        String baseUrl = gscapiConfig.getBaseUrl();
        String getBFCustomItems = gscapiConfig.getApis().get("getBFCustomItems");
        String url = baseUrl + getBFCustomItems;
        System.out.println(url);
        // 置入Query参数
        String uri = HttpUtil.putQueryParam(url, null);
        // 置入Header参数
        HttpHeaders headers = new HttpHeaders();
        headers.addAll(new LinkedMultiValueMap<>(gscapiConfig.getRequestHeaders()));
        // 置入Body参数, 这里要用Map而不是普通MultiValueMap
        /**
         * {
         *     "Date":"2024-01-09 02:00:48",
         *     "HSZZID":"010511",
         *     "YEAR": "2024"
         * }
         */

        Map<String, Object> bodyParam = new HashMap<>();
        bodyParam.put("YEAR", year);
        bodyParam.put("HSZZID", hszzid);
        bodyParam.put("Date", lastChangedOn);

        // 组织参数
        HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(bodyParam, headers);
        // 发送请求
        ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, String.class);
        // 解析结果
        if(response.getStatusCodeValue() == 200){
            String responseBody = response.getBody();
            // 处理结果数据 JSON字符串
            return parseCustomItem(responseBody);

        }else{
            System.out.println(response.getStatusCode());
            System.out.println(response.getStatusCodeValue());
            System.out.println(response.getHeaders());
            System.out.println(response.getBody());
            return null;
        }
    }

    /**
     * 解析GSC账务核算项目字典数据JSON字符串
     *
     * @param jsonStr GSC账务核算项目字典数据JSON字符串
     * @return GSC账务核算项目数组
     */
    @Override
    public List<BFCustomItem> parseCustomItem(String jsonStr) {
        // 解析Json字符串
        JSONObject jsonObject = JSON.parseObject(jsonStr);
        Boolean result = jsonObject.getBoolean("result");
        String code = jsonObject.getString("code");//获取字符串
        if(result) {
            log.info("请求核算项目数据成功");
            JSONArray value = jsonObject.getJSONArray("value");
            List<BFCustomItem> customItemList = new ArrayList<>();
            int countItem = value.size();
            for (int i = 0; i < countItem; i++) {
                JSONObject element = value.getJSONObject(i);
                BFCustomItem customItem = ESUNGSCUtil.jsonObject2BFCustomItem(element);
                // 加入到customItemList中
                customItemList.add(customItem);
            }

            return customItemList;
        }else{
            log.error("请求核算项目数据失败");
            return null;
        }
    }

    /**
     * GSC账务核算项目数组存入数据库，其中ID+YEAR重复的会覆盖
     *
     * @param customItemList GSC账务核算项目数组
     */
    @Override
    public void syncCustomItemList(List<BFCustomItem> customItemList) {
        for (BFCustomItem customItem : customItemList) {
            bfCustomeItemService.syncSave(customItem);
        }
    }
}
